package com.gjy.shiro.simple;

import com.google.common.collect.Sets;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @author gjy
 * @version 1.0
 * @since 2025-09-01 15:00:04
 */
public class SimpleRealmSalt extends AuthorizingRealm {

    private static final Logger log = LoggerFactory.getLogger(SimpleRealmSalt.class);

    // 模拟 DAO
    private static final Map<String, UserInfo> USER_REPO = new HashMap<>();

    static {
        UserInfo alice = new UserInfo("alice", PasswordUtil.encrypt("alice"), Sets.newHashSet("user"), Sets.newHashSet("emp:view"));
        UserInfo bob = new UserInfo("bob", PasswordUtil.encrypt("123456"), Sets.newHashSet("admin"), Sets.newHashSet("emp:view", "emp:edit", "emp:delete"));
        USER_REPO.put("alice", alice);
        USER_REPO.put("bob", bob);
    }

    public SimpleRealmSalt() {
        // 1. 设置 CredentialsMatcher
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName(PasswordUtil.ALGORITHM); // SHA-256
        matcher.setHashIterations(PasswordUtil.ITERATIONS);   // 1024
        matcher.setStoredCredentialsHexEncoded(true);         // 十六进制
        setCredentialsMatcher(matcher);
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        UserInfo user = USER_REPO.get(username);

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(user.getRoles());
        info.setStringPermissions(user.getPermissions());
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        UserInfo user = USER_REPO.get(username);
        if (user == null) {
            throw new UnknownAccountException("用户不存在：" + username);
        }
        // 解析存储的 salt:hash
        String[] parts = user.getPasswordMd5().split(":");
        // ByteSource salt = ByteSource.Util.bytes(new SecureRandomNumberGenerator().nextBytes(16).getBytes());
        ByteSource salt = ByteSource.Util.bytes(Base64.decode(parts[0]));
        String hashedPassword = parts[1];

        return new SimpleAuthenticationInfo(user.getUsername(), hashedPassword, salt, getName());
    }
}
